package com.example.camunda.service;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.engine.HistoryService;
import org.camunda.bpm.engine.RepositoryService;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.TaskService;
import org.camunda.bpm.engine.history.HistoricProcessInstance;
import org.camunda.bpm.engine.history.HistoricTaskInstance;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.camunda.bpm.engine.task.Task;
import org.camunda.bpm.engine.task.TaskQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
@Slf4j
public class ProcessEngineService {
    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;

    private static final String PROCESS_INSTANCE_KEY = "settlement-pay-one-node";

    public void getDeployedRepository() {
        List<String> deployedRepositories = repositoryService.getDeploymentResourceNames("1901");
        for (String deployedRepository : deployedRepositories) {
            log.info("已发布模型:{}", deployedRepository);
        }
    }

    /**
     * 启动一个流程(发起申请)
     * <p>
     * 实例ID：2182
     * 任务ID：2185
     */
    public void startProcess() {
        // 启动一个流程
        String businessKey = "JS00000000001";
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(PROCESS_INSTANCE_KEY, businessKey);
        // 获取流程实例ID
        String processInstanceId = processInstance.getProcessInstanceId();
        log.info("\n实例ID：{}", processInstanceId);
        // 查找当前申请任务
        Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
        log.info("\n任务ID：{}", task.getId());
        String applierName = "张三";
        // 申明任务
        taskService.claim(task.getId(), applierName);
        log.info("\n申明任务成功，申明人：{}", applierName);
        String candidateUserName = "李四";
        // 设置受理人
        taskService.setAssignee(task.getId(), candidateUserName);
        // 完成申请节点任务
        Map<String, Object> variables = new HashMap<>(4);
        variables.put("applierId", "1235456");
        variables.put("applierName", applierName);
        taskService.complete(task.getId(), variables);
        log.info("\n任务申请成功");

        // 设置下一节点受理人，assignee在实际业务中设置为用户ID
        String currentProcessInstanceId = task.getProcessInstanceId();
        Task nextTask = taskService.createTaskQuery().processInstanceId(currentProcessInstanceId).singleResult();
        log.info("task definition key is : " + nextTask.getTaskDefinitionKey());
        log.info("下一节点ID:{}", nextTask.getId());
        log.info("下一流程实例ID:{}", nextTask.getProcessInstanceId());
        taskService.setAssignee(nextTask.getId(), "张三");
    }

    /**
     * 查询所有激活状态的流程
     */
    public void findAllActiveProcess() {
        List<HistoricProcessInstance> finishedProcessInstances = historyService.createHistoricProcessInstanceQuery().active().list();
        for (HistoricProcessInstance finishedProcessInstance : finishedProcessInstances) {
            log.info("实例ID：{}", finishedProcessInstance.getId());
            log.info("实例状态：{}", finishedProcessInstance.getState());
            log.info("业务key：{}", finishedProcessInstance.getBusinessKey());
        }
    }

    /**
     * 查询所有完成状态的流程
     */
    public void findAllFinishedProcess() {
        List<HistoricProcessInstance> finishedProcessInstances = historyService.createHistoricProcessInstanceQuery().finished().list();
        for (HistoricProcessInstance finishedProcessInstance : finishedProcessInstances) {
            log.info("实例ID：{}", finishedProcessInstance.getId());
            log.info("实例状态：{}", finishedProcessInstance.getState());
            log.info("业务key：{}", finishedProcessInstance.getBusinessKey());
        }
    }

    /**
     * 查找所有待处理的任务
     */
    public void findAllPendingTask() {
        List<Task> taskList = taskService.createTaskQuery().orderByTaskPriority().desc().list();
        for (Task task : taskList) {
            log.info("\n" +
                            "任务ID：{}\n" +
                            "任务时间：{}\n" +
                            "任务任务受理人：{}\n" +
                            "任务任务名称：{}\n" +
                            "流程定义ID：{}\n" +
                            "流程实例ID：{}\n",
                    task.getId(), task.getCreateTime(), task.getAssignee(), task.getName(), task.getProcessDefinitionId(), task.getProcessInstanceId());
        }

    }

    public void completeTask() {
        // 通过createTaskQuery()获取参数
        String taskId = "2666";
        String processInstanceId = "2654";
        String comment = "同意";
        taskService.createComment(taskId, processInstanceId, comment);
        String auditorUser = "李四";
        Map<String, Object> variables = new HashMap<>(4);
        variables.put("applierId", "1235457");
        variables.put("auditorUser", auditorUser);
        taskService.complete(taskId, variables);
        // 获取当前节点后的下一个待执行节点
        // 如果为空，且审批通过，可以认为当前审批流已结束，可以紧跟着更新业务状态
        Task nextTask = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
        if (Objects.nonNull(nextTask)) {
            // 下一节点流程定义ID用以区分为第几级审批人
            log.info("下一节点流程定义ID: " + nextTask.getTaskDefinitionKey());
            log.info("下一节点ID:{}", nextTask.getId());
            log.info("下一流程实例ID:{}", nextTask.getProcessInstanceId());
            taskService.setAssignee(nextTask.getId(), "张三");
        }

    }


    public void createTaskQuery() {
        // 查询任务
        TaskQuery taskQuery = taskService.createTaskQuery()
                .processDefinitionKey(PROCESS_INSTANCE_KEY);
        List<Task> taskList = taskQuery.list();
        for (Task task : taskList) {
            log.info("\n" +
                            "任务ID：{}\n" +
                            "任务时间：{}\n" +
                            "任务任务受理人：{}\n" +
                            "任务任务名称：{}\n" +
                            "流程定义ID：{}\n" +
                            "流程实例ID：{}\n",
                    task.getId(), task.getCreateTime(), task.getAssignee(), task.getName(), task.getProcessDefinitionId(), task.getProcessInstanceId());

        }
    }

    /**
     * 创建一个流程实例查询
     */
    public void createProcessInstanceQuery() {
        String processInstanceId = "104";
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                //结果唯一的，可以用single，如果大于1，则会报错
                .singleResult();
        if (processInstance == null) {
            log.info("当前实例已经结束了");
        } else {
            log.info("当前实例正在运转");
        }
    }

    public void createHistoricTaskInstanceQuery() {
        String processInstanceId = "2182";
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId)
                .list();
        for (HistoricTaskInstance historicTaskInstance : list) {
            log.info("历史任务实例ID：{}", historicTaskInstance.toString());
        }
        List<HistoricTaskInstance> finishedTask = historyService.createHistoricTaskInstanceQuery().finished().list();
        for (HistoricTaskInstance historicTaskInstance : finishedTask) {
            log.info("已完成的历史任务实例：{}", JSON.toJSONString(historicTaskInstance));
        }
    }

    /**
     * 删除一个流程实例，并且删除其下相关任务
     *
     * 可以用于审批驳回
     */
    public void deleteHistoricProcessInstance() {
        String processInstanceId = "2182";
        historyService.deleteHistoricProcessInstance(processInstanceId);
        log.info("流程{}删除成功", processInstanceId);
    }



}
